//#include "treeFileIO.hpp"
//using namespace DTree;


//Saves a Tree to file.
template<class Node_Type>
TreeFileIO<Node_Type>::TreeFileIO(const Node_Type* root, std::ostream& outStream)
{
	if(!root)
		throw 0;
	
	SaveTree(0, *root, outStream);

}

//Loads a tree in from file
template<class Node_Type>
TreeFileIO<Node_Type>::TreeFileIO(Node_Type*& root, std::istream& inStream)
{
	if(root)
		delete root;

	LoadTree(0, root, inStream);
	

}

//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
StripDelimiter(unsigned int tabCount, char* buffer)//std::istream& inStream)
{
	while(buffer[0] == TREE_DELIMITER)
		memmove(buffer, buffer+1, sizeof(char) + strlen(buffer));
}


//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
WriteBranch(const Node_Type& node, std::ostream& outStream)
{
	//stream the header
	outStream << TREE_BRANCH;//"This is a branch";

	//nead to save index and value
	outStream << "Pred: " << node.GetPredType();
	outStream << "  Case Index: " << node.GetCaseIndex();
	outStream << "  Case Value: " << node.GetCaseValue();
	return;
}


//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
WriteLeaf(const Node_Type& node, std::ostream& outStream)
{
	//stream in header
	outStream << TREE_LEAF;//"This is a leaf";

	//save the class to file. Each class will need to have its << operator overloaded.
	outStream << "Class: " << node.GetClass();
	return;
}


//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
ReadBranch(Node_Type& node, const char* buffer)//std::istream& inStream)
{
	//Assume the header was already read in.
	//...

	//read in the Case index and value.
	DTree::NodePredicate pred;
	unsigned CaseIndex = 0;
	float	CaseValue = 0;

	sscanf(buffer, "Pred: %c  Case Index: %d  Case Value: %f", &pred, &CaseIndex, &CaseValue);

	node.SetPredType(pred);
	node.SetCaseIndex(CaseIndex);
	node.SetCaseValue(CaseValue);	

	return;
}

#pragma warning(push)
#pragma warning(disable: 4800)
//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
ReadLeaf(Node_Type& node, const char* buffer)//std::istream& inStream)
{
	//Assume that the header character was already read in
	//...

	//Read in the class
	bool ClassVal = 0;
	sscanf(buffer, "Class: %d", &ClassVal);
	node.SetClass(ClassVal);
	return;
}
#pragma warning(pop)

//See header for documentation.
template<class Node_Type>
void TreeFileIO<Node_Type>::
SaveTree(unsigned int tabCount, const Node_Type& node, std::ostream& outStream)
{
	//Feed in the relevent ammount of delimiters.
	FeedDelimiter(tabCount, outStream);


	//Test to see if this is a branch
	if(node.GetLeft() && node.GetRight())
	{
		//Writes a branch to the stream
		WriteBranch(node, outStream);

		//recurse left.
		SaveTree(tabCount + 1, *(node.GetLeft()), outStream << std::endl);

		//recurse right
		SaveTree(tabCount + 1, *(node.GetRight()), outStream << std::endl);
	}
	

	//otherwise save this as a leaf
	else
	{
		//Write this a leaf to the stream.
		WriteLeaf(node, outStream);
	}	
}


inline char GetHeader(char* buffer)
{
	char retVal = buffer[0];
	memmove(buffer, buffer+1, sizeof(char) + strlen(buffer));
	return retVal;
}

template<class Node_Type>
void TreeFileIO<Node_Type>::
LoadTree(unsigned int tabCount, Node_Type*& node, std::istream& inStream)
{

	node = new Node_Type;

	char buffer[512] ={0};

	//read in lines, skip lines that begin with a '#'.
	do {
		inStream.getline(buffer, 512);
	} while(strstr(buffer, "#"));
	

	//Strip away delimiters.
	StripDelimiter(tabCount, buffer);



	//Test stream to see if this node is a branch or leaf
	char header = GetHeader(buffer);

	//Will be true if this is a branch
	if(header == TREE_BRANCH)
	{
		//read in the branch
		ReadBranch(*node, buffer);

		//recurse
		LoadTree(tabCount + 1, node->m_left, inStream);
		LoadTree(tabCount + 1, node->m_right, inStream);
	}

	//will be true if this is a leaf
	else if(header == TREE_LEAF)
	{
		ReadLeaf(*node, buffer);
	}

	//If we enter this case then the file was garbled. throw an exception.
	else
		throw header;
	
	return;
}